package es.duma.presentation;

import es.duma.search.SearchService;
import es.duma.search.SearchServiceHome;
import es.duma.util.config.Configurator;
import es.duma.util.log.Log;
import es.duma.util.xmlparse.search.DumaSearch;
import es.duma.util.xmlparse.search.ObjectFactory;
import es.duma.util.xmlparse.search.DumaSearch.Search;
import es.duma.util.xmlparse.search.DumaSearch.Author;


import java.io.ByteArrayOutputStream;
import java.io.OutputStream;

import java.util.Collection;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.naming.Context;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import javax.rmi.PortableRemoteObject;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

/**
 * Contruye el xml de busqueda universl definido para el servicio DUMA a partir de los
 * parametros de la busqueda de usuario recibida.
 */
public class SearchManager {
    
    /**
     * Modificador especial en la busqueda. No incluir la palabra clave seguida de este elemento
     */
    private static final String NOT_KEY="-";
    
    /**
     * Modificador especial en la busqueda. Busqueda por autor
     */
    private static final String SEARCH_OWNER="owner:";
    private static final String SEARCH_AUTHOR="autor:";
    
    /**
     * Modificador especial en la busqueda. Busqueda por tipo de contenido
     */
    private static final String SEARCH_MEDIA="media:";
    
    
    /**
     * Objeto que encapsula en xml de busqueda construido
     */
    private DumaSearch dumaSearch;
    
    
    /**
     * Constructor de la clase
     *
     * @param cadena cadena de busqueda de usuario
     */
    public SearchManager(String cadena) {
        Log.debug(this,"Cadena recibida para la busqueda: "+cadena);
        
        //Mapear la cadena al XML
        ObjectFactory factory =  new ObjectFactory();
        dumaSearch= factory.createDumaSearch();
        
        //Elemento search del xml
        Search search=factory.createDumaSearchSearch();
        //Elemento author del xml
        Author author=factory.createDumaSearchAuthor();
       

        //Se tokeniza la cadena con el espacio blanco como caracter de separacion para obtener todas las palabras
        StringTokenizer tokens = new StringTokenizer(cadena);
        Log.debug(this,"Se obtienen los terminos de busqueda de la cadena recibida");


        // Se procesan los tokens obtenidos de la cadena de busqueda
        while (tokens.hasMoreElements()){
            String key=(String)tokens.nextElement();
            
            //Procesar operadores sobre la cadena de busqueda    
            //Caracter negacion
            if(key.startsWith(NOT_KEY)){
                Log.debug(this,"Operador de negacion encontrado "+key);
                search.getNotkey().add(key.substring(NOT_KEY.length()));
            }else if ((key.startsWith(SEARCH_OWNER)|| key.startsWith(SEARCH_AUTHOR))){
                String owner=key.substring(SEARCH_OWNER.length());
                Log.debug(this,"Se ha incluido una busqueda por propietario owner->"+owner);                
                author.setUserId(owner);
            }else if ((key.startsWith(SEARCH_MEDIA))){
                Log.debug(this,"Se ha incluido un filtro de contenido en la busqueda");
            }else{
                Log.debug(this,"Termino de busqueda: "+key);
                search.getKey().add(key);  
            }}

        //Se fija el nodo search           
        dumaSearch.setSearch(search);
        //Se fija el nodo author
        dumaSearch.setAuthor(author);
    }
    
    
    /**
     * Se obtiene el XML de busqueda en un String para poder enviar por RMI
     * @return
     */
    public String getXMLString(){
        Log.debug(this,"Se ha iniciado la obtencion del xml en un String");
        JAXBContext jaxbContext;
        OutputStream out=new ByteArrayOutputStream();;
        try {
            jaxbContext = JAXBContext.newInstance("es.duma.util.xmlparse.search");
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.marshal(this.dumaSearch, out);
        } catch (JAXBException e) {
            Log.error(this,""+e); 
        }
        return out.toString();
   
    }
    
    /**
     * Lanza la peticion de la busqueda contra el Servicio de busqueda DUMA
     * @param xmlSearch
     * @return
     */
    public String execSearch(String xmlSearch){
        String result="";
        //Conectar RMI y esas cosas
         try {
             final Context context = getInitialContext();
             final SearchServiceHome searchServiceHome = 
                 (SearchServiceHome) PortableRemoteObject.narrow( context.lookup( "SearchService" ), SearchServiceHome.class );
             SearchService searchService;
             searchService = searchServiceHome.create(  );
             // Call any of the Remote methods below to access the EJB
             result=searchService.search(xmlSearch);
             //Mostrar el resultado por log
             //Log.debug(this,"El resultado obtenido en Mpeg7 es:"+ result);
         } catch (Exception ex) {
             ex.printStackTrace();
         }
        return result;
    }
    
    /**
     * Obtiene el contexto para invocar el EJB de sesion (SearchService) que implementa el servicio de busqueda DUMA
     * @return
     * @throws NamingException
     */
    private static Context getInitialContext() throws NamingException {
        Hashtable env = new Hashtable();
        //  Standalone OC4J connection details
         env.put( Context.INITIAL_CONTEXT_FACTORY, Configurator.getPropertieValue("INITIAL_CONTEXT_FACTORY"));
         env.put( Context.SECURITY_PRINCIPAL, Configurator.getPropertieValue("SECURITY_PRINCIPAL") );
         env.put( Context.SECURITY_CREDENTIALS, Configurator.getPropertieValue("SECURITY_CREDENTIALS") );
         env.put(Context.PROVIDER_URL, Configurator.getPropertieValue("PROVIDER_URL_SEARCH_SERVICE"));
        return new InitialContext( env );
    }
    
    
    
}
